package com.zy.cat.common.utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.springframework.util.DigestUtils;

import com.alibaba.fastjson.JSON;

import lombok.extern.slf4j.Slf4j;

@Slf4j
/**
 * 
 * @info 微信支付xml请求参数工具类
 * @author Link
 * @date 2019-12-16 14:46
 */
public class WXPayUtils {
	private static final String key = "1eff210fbd7c29a61aaefc00e793ec3b";
 

	/**
	 * 
	 * @info 获取微信签名信息
	 * @author Link
	 * @date 2019-12-16 10:07
	 * @param stype  签名类型：0.MD5 1.HMAC-SHA256
	 * @param params
	 * @param key
	 * @return
	 */
	private static String getWePay2UserSign(int stype, Map<String, String> params) {
		String result = null;

		StringBuilder sb = new StringBuilder();

		Map<String, Object> sortParams = new TreeMap<String, Object>(params);
		for (Map.Entry<String, Object> entry : sortParams.entrySet()) {
			if (sb.length() != 0) {
				sb.append("&");
			}
			sb.append(entry.getKey()).append("=").append(entry.getValue());
		}
		result = sb.toString() + "&key=" + key;
		if (stype == 0) {
			result = DigestUtils.md5DigestAsHex(result.getBytes()).toUpperCase();
		} else {
			result = sha256_HMAC(result, key).toUpperCase();
		}
		return result;
	}

	/**
	 * sha256_HMAC加密
	 * 
	 * @param message 消息
	 * @param secret  秘钥
	 * @return 加密后字符串
	 */
	private static String sha256_HMAC(String message, String secret) {
		String hash = "";
		try {
			Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
			SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
			sha256_HMAC.init(secret_key);
			byte[] bytes = sha256_HMAC.doFinal(message.getBytes());
			hash = byteArrayToHexString(bytes);
		} catch (Exception e) {
			System.out.println("Error HmacSHA256 ===========" + e.getMessage());
		}
		return hash;
	}

	/**
	 * 将加密后的字节数组转换成字符串
	 *
	 * @param b 字节数组
	 * @return 字符串
	 */
	private static String byteArrayToHexString(byte[] b) {
		StringBuilder hs = new StringBuilder();
		String stmp;
		for (int n = 0; b != null && n < b.length; n++) {
			stmp = Integer.toHexString(b[n] & 0XFF);
			if (stmp.length() == 1)
				hs.append('0');
			hs.append(stmp);
		}
		return hs.toString().toLowerCase();
	}

	/**
	 * 
	 * @info 解析map2xml
	 * @author Link
	 * @date 2019-12-16 10:21
	 * @param map
	 * @return
	 */
	private static String callMapToXML(Map<String, String> map) {
		StringBuffer sb = new StringBuffer();
		sb.append("<xml>");
		mapToXML(map, sb);
		sb.append("</xml>");
		try {
			return sb.toString();
		} catch (Exception e) {
		}
		return null;
	}

	/**
	 * 
	 * @info 递归解析map2xml
	 * @author Link
	 * @date 2019-12-16 14:39
	 * @param map
	 * @param sb
	 */
	private static void mapToXML(Map map, StringBuffer sb) {
		Set set = map.keySet();
		for (Iterator it = set.iterator(); it.hasNext();) {
			String key = (String) it.next();
			Object value = map.get(key);
			if (null == value)
				value = "";
			if (value.getClass().getName().equals("java.util.ArrayList")) {
				ArrayList list = (ArrayList) map.get(key);
				sb.append("<" + key + ">");
				for (int i = 0; i < list.size(); i++) {
					HashMap hm = (HashMap) list.get(i);
					mapToXML(hm, sb);
				}
				sb.append("</" + key + ">");
			} else {
				if (value instanceof HashMap) {
					sb.append("<" + key + ">");
					mapToXML((HashMap) value, sb);
					sb.append("</" + key + ">");
				} else {
					sb.append("<" + key + "><![CDATA[" + value + "]]></" + key + ">");
				}

			}
		}
	}
	
	/**
	 * 
	 * @info 获取微信打款请求参数
	 * @author Link
	 * @date 2019-12-16 14:43
	 * @param stype
	 * @param params
	 * @return
	 */
	public static Map<String, String> getWxPayXml(int stype,Map<String, String> params){
		Map<String, String> result = new HashMap<String, String>();
		String sign = getWePay2UserSign(stype, params);
		params.put("sign", sign);
		log.info("-sign-->" + sign);
		String strxml = callMapToXML(params);
		log.info("-strxml-->" + strxml);
		result.put("XML", strxml);
		result.put("ID", params.get("mchid"));
		return result;
	}

	public static void main(String[] args) {
		Map<String, String> result ;
		Map<String, String> params = new HashMap<String, String>();

		// ocklkwkvtHtgpMonMCSXWwWjShck
		/* 商户账号appid:申请商户号的appid或商户号绑定的appid */
		params.put("mch_appid", "wxc146995ce70eb12e");

		/* 商户账号appid:微信支付分配的商户号 */
		params.put("mchid", "1502373641");

		/* 随机字符串 */
//		params.put("nonce_str", UUID.randomUUID().toString().replace("-", ""));
		params.put("nonce_str", "e6ae61691abf9ed8bfe8f734e211");

		/* 商户订单号:商户订单号，需保持唯一性(只能是字母或者数字，不能包含有其他字符) */
//		params.put("partner_trade_no", UUID.randomUUID().toString().replace("-", ""));
		params.put("partner_trade_no", "5fa898ba4e95b823d3bbf5f0ed11");

		/* 用户openid:商户appid下，某用户的openid */
		params.put("openid", "om19Bs7yW9VVQnqtV-v6r2OdFNOY");

		/* 校验用户姓名选项:NO_CHECK：不校验真实姓名 FORCE_CHECK：强校验真实姓名 */
		params.put("check_name", "NO_CHECK");

		/* 金额:企业付款金额，单位为分 */
		params.put("amount", "1");

		/* 企业付款备注:企业付款备注，必填。注意：备注中的敏感词会被转成字符* */
		params.put("desc", "九趣猫提现");

		/* Ip地址:该IP同在商户平台设置的IP白名单中的IP没有关联，该IP可传用户端或者服务端的IP。47.104.254.237 */
		params.put("spbill_create_ip", "47.104.254.237");

		result = getWxPayXml(0, params);

		log.info("result-->" + JSON.toJSONString(result));

	}
}
